package com.vii.brillien.services.websocket.applications.purity;

import com.vii.brillien.core.management.BrillienServices;
import com.vii.brillien.ignition.BrillienContext;
import com.vii.brillien.ignition.transport.BrillienCommunication;
import com.vii.brillien.ignition.transport.BrillienMediator;
import com.vii.brillien.ignition.transport.LoaderComplyer;
import com.vii.brillien.kernel.BrillienException;
import com.vii.streamline.purity.PurityServlet;
import com.vii.streamline.services.error.StreamLineException;
import com.vii.streamline.services.json.JsonServices;
import com.vii.streamline.web.HttpServices;
import org.apache.http.HttpStatus;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Specialized HttpServlet to able to delegate BrillienCommunication calls to presences.
 */
public class PureServlet extends PurityServlet {

    protected static PureServlet servletInstance;

    static{
        servletInstance = new PureServlet();
    }

    protected BrillienMediator                  mediator;

    public static PureServlet getServletInstance() {
        return servletInstance;
    }


    {
        initMediatorContext();

        initReferences();
    }


    protected void initMediatorContext(){

    }

    protected void setupMediatorContext( ServletConfig servletConfig ){

    }

    protected void initReferences(){

    }

    protected BrillienMediator getMediator() throws ServletException {
        if( mediator == null ){
            String username = getServletConfig().getInitParameter("username");
            String password = getServletConfig().getInitParameter("password");
            if( username == null ){
                username = "dispatcher" + this.getClass().getSimpleName(); password = "dispatcher";
            }
            try {
                if( mediator == null ){
                    setupMediatorContext( getServletConfig() );
                    mediator = BrillienContext.newMediator(username, password, new LoaderComplyer() {
                        @Override
                        public ClassLoader getLoader(String reference) {
                            try {
                                return BrillienServices.getPresenceManagerByName(
                                        BrillienServices.liaison,reference).getClassLoader();
                            } catch (BrillienException e) {
                                e.printStackTrace();
                                return this.getClass().getClassLoader();
                            }
                        }
                    });
                    mediator.connect();
                }
            } catch (BrillienException e) {
                throw new ServletException( e.getMessage(), e );
            }
        }
        return mediator;
    }

    @Override
    public void init() throws ServletException {
        super.init();

        getMediator();
    }

    @Override
    protected void sendError(HttpServletRequest req, HttpServletResponse resp, int errorCode, String errorMessage, Object errorValue) {
        try {
            resp.setStatus( HttpStatus.SC_BAD_REQUEST );
            BrillienCommunication comm = mediator.newErrorCommunication(errorCode, errorMessage, errorValue);
            if( logger != null )
                logger.debug( "Sending error message:" + comm );
            HttpServices.sendJSONMessage(req, resp, comm );
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    protected Object call(String requestString) throws StreamLineException{
        PureCommunication comm = JsonServices.parseJSON( requestString, PureCommunication.class );

        try {
            return mediator.sendCommunication( comm );
        } catch (BrillienException e) {
            throw new StreamLineException( e.getErrorCode(), e.getMessage(), e.getValue() );
        }
    }

    @Override
    public void destroy() {
        try {
            if( mediator != null )
                mediator.disconnect();
        } catch (BrillienException e) { }
        BrillienContext.cleanup();
    }

}
